/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package earleyalgorithm;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 *
 * @author NGOC
 */
public class Grammar {
    String name;
    Map<Category, Set<Rule>> rules;
    static Category startCategory;

    public Grammar(String name, Category start) {
	this.name = name;
        startCategory = start;
	rules = new HashMap<Category, Set<Rule>>();
    }


    public String getName() {
	return name;
    }

    public static void setStartCategory(Category c){
        startCategory = c;
    }

    public boolean addRule(Rule rule) {
	if(rule == null) {
            throw new NullPointerException("null rule");
	}

	Set<Rule> r;
	if(!rules.containsKey(rule.left)) { // already rules for rule.left?
            r = new HashSet<Rule>();
            rules.put(rule.left, r); // create, add rule set at rule.left
	}
	else {
            r = rules.get(rule.left); // get the existing rule set
	}

	return r.add(rule);
    }

    public boolean containsRules(Category left) {
	return rules.containsKey(left);
    }

    public Set<Rule> getRules(Category left) {
	return rules.get(left);
    }

    public Set<Rule> getAllRules() {
	Set<Rule> allRules = new HashSet<Rule>();

	for(Set<Rule> s : rules.values()) {
            allRules.addAll(s);
	}

	return allRules;
    }

    Rule getSingletonPreterminal(Category left, String token, boolean ignoreCase) {
	if(rules.containsKey(left)) {
            for(Rule r : rules.get(left)) {
		if(r.isSingletonPreterminal() && (r.right[0].name.equals(token) || (ignoreCase
                    && r.right[0].name.equalsIgnoreCase(token)))) {
                    return r;
		}
            }
	}

	return null;
    }

    @Override
    public String toString() {
	StringBuilder sb = new StringBuilder("");

	Iterator<Set<Rule>> si = rules.values().iterator();
	while(si.hasNext()) {
            Iterator<Rule> ri = si.next().iterator();
            while(ri.hasNext()) {
                sb.append(ri.next().toString());
		if(ri.hasNext()) {
                    sb.append("\n");
		}
            }

            if(si.hasNext()) {
		sb.append("\n");
            }
	}

	//sb.append("}]");

	return sb.toString();
    }

}
